package com.guavamail.smtp.command;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

import org.apache.mina.core.session.IoSession;

import com.guavamail.smtp.SMTPConnectionHandler;
import com.guavamail.smtp.SMTPContext;
import com.guavamail.smtp.command.impl.*;
import com.guavamail.smtp.exception.CommandException;

public class CommandHandler {
	private static final Map<String, Command> DEFAULT_COMMAND_MAP = new HashMap<String, Command>();

	static {
		DEFAULT_COMMAND_MAP.put("EHLO", new EHLO());
		DEFAULT_COMMAND_MAP.put("HELO", new HELO());
		DEFAULT_COMMAND_MAP.put("MAIL", new MAIL());
		DEFAULT_COMMAND_MAP.put("RCPT", new RCPT());
		DEFAULT_COMMAND_MAP.put("DATA", new DATA());
		DEFAULT_COMMAND_MAP.put("QUIT", new QUIT());
		DEFAULT_COMMAND_MAP.put("RSET", new RSET());
		DEFAULT_COMMAND_MAP.put("NOOP", new NOOP());
		DEFAULT_COMMAND_MAP.put("HELP", new HELP());
		DEFAULT_COMMAND_MAP.put("AUTH", new AUTH());
	}

	/**
	 * 依据命令行获取对应指令处理程序
	 * 
	 * @param commandString
	 * @return
	 * @throws CommandException
	 */
	public Command getCommand(final String commandString) throws CommandException {
		String verb = toVerb(commandString);

		Command command = DEFAULT_COMMAND_MAP.get(verb);
		if (command == null)
			throw new CommandException("Command not implemented");
		return command;
	}

	/**
	 * 判断是否存在某命令
	 * 
	 * @param command
	 * @return
	 */
	public static boolean containsCommand(String command) {
		return DEFAULT_COMMAND_MAP.containsKey(command);
	}

	/** */
	private String toVerb(String string) throws CommandException {
		if (string == null || string.length() < 4)
			throw new CommandException("Syntax error");

		StringTokenizer st = new StringTokenizer(string);

		if (!st.hasMoreTokens())
			throw new CommandException("Syntax error");

		return st.nextToken().toUpperCase();
	}

	/**
	 * 依据命令执行操作
	 * 
	 * @param commandString
	 * @param session
	 * @param ctx
	 * @throws IOException
	 */
	public void handleCommand(String commandString, IoSession session, SMTPContext ctx) throws IOException {
		try {
			Command cmd = getCommand(commandString);
			cmd.execute(commandString, session, ctx);
		} catch (CommandException e) {
			SMTPConnectionHandler.sendResponse(session, "500 " + e.getMessage());
		}
	}

}
